﻿#include "MainView.h"
#include <QSettings>
#include <QFileDialog>
#include "PublicMacros.h"
#include "BackTestOperator.h"
#include "SpecialPriceSeacher.h"
#include "KItemUI.h"
#include "MDLoginSetting.h"
#include "TradeLoginSetting.h"
#include "Tools.h"
#include "SymbolDetail.h"
#include "GenBaseKItemControl.h"
#include "CTPTime.h"
#include "StrategyOptionUI.h"
#include "HolidayOptionUI.h"
#include "OptionManager.h"
#include "TestPriceTime.h"
#include "MetricesPainter.h"
#include "DateTimeTickerText.h"

MainView::MainView(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	showMaximized();
	initCandles();

	connect(ui.act_workspace, SIGNAL(triggered()), this, SLOT(onSetWorkspace()));
	//connect(ui.centralWidget, SIGNAL(operateInfo(const QString& )), this, SLOT(showOperateMessage(const QString&)));
	ui.list_symbols->setContextMenuPolicy(Qt::CustomContextMenu);
	initSymbolListInfo();
}

MainView::~MainView()
{
	saveBackTime(getMarketTimeMiddle());
}

void MainView::onSetWorkspace()
{
	std::string pworkspace = OptionManager::Instance().GetWorkDir();
	QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), QString::fromLocal8Bit(pworkspace.c_str()), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
	if (!dir.isEmpty())
	{
		OptionManager::Instance().SetWorkDir(dir.toLocal8Bit().data());
	}
}

void MainView::showOperateMessage(const QString &pMsg)
{
	ui.statusBar->showMessage(pMsg, 5000);
}

void MainView::generateKItem()
{
	GenBaseKItemControl genBaseK(ui.list_symbols, this);
	genBaseK.GenAllPrice();
}

void MainView::slotTest()
{
	//SpecialPriceSeacher seacher(nullptr);
	//seacher.FindDiffValueOpenPrice("ag2112", "2021-09-10");
	//TestHoliday testHoliday;
	////testHoliday.TestHolidayDay(50);
	//testHoliday.TestWorkTime();

	TestPriceTime testPrice("2022-01-26");
	testPrice.StartTest();
}

void MainView::onChangeBackTestTime(const QDateTime &datetime)
{
	std::list<std::string> symbolList;
	SymbolPackage::GetTheLastMainSymbolList(symbolList, datetime.toTime_t());
	SymbolPackage::OrderSymbolReaderWriter orderSymbols;
	orderSymbols.GetSymbolList(symbolList);
	std::set<std::string> symbolsSet;
	for (std::list<std::string>::iterator it = symbolList.begin(); it != symbolList.end(); ++it)
	{
		symbolsSet.insert(*it);
	}
	ui.list_symbols->clear();
	for (std::set<std::string>::iterator it = symbolsSet.begin(); it != symbolsSet.end(); ++it)
	{
		ui.list_symbols->addItem(it->c_str());
	}
	onCheckStateChanged(Qt::Unchecked);
	ui.check_selectAll->setCheckState(Qt::Unchecked);
}

//void MainView::setBackTime()
//{
//	ui.dateTime_backTestTo->setDateTime(QDateTime::currentDateTime());
//}

void MainView::onCheckStateChanged(int state)
{
	Qt::CheckState isSelected = state == Qt::Checked ? Qt::Checked : Qt::Unchecked;
	for (int i = 0; i < ui.list_symbols->count(); ++i)
	{
		ui.list_symbols->item(i)->setCheckState(isSelected);
	}
}

void MainView::onStartBackTest()
{
	// 首先列出所有选中合约
	QStringList symbolNameSets;
	for (int i = 0; i < ui.list_symbols->count(); ++i)
	{
		QListWidgetItem *pItem = ui.list_symbols->item(i);
		if (pItem->checkState() != Qt::Checked)
		{
			continue;
		}
		symbolNameSets << pItem->text();
	}
	// 获取回测时间
	time_t backTestRangeBeginStamp, backTestRangeEndStamp;
	getCurBackTestTime(backTestRangeBeginStamp, backTestRangeEndStamp);
	MetricsDataGather pDataGather;
	BackTestOperator operTest(&pDataGather);
	for (QStringList::iterator it = symbolNameSets.begin(); it != symbolNameSets.end(); ++it)
	{
		std::string stdSymbolName = it->toLocal8Bit().data();
		operTest.BackTest(stdSymbolName, backTestRangeBeginStamp, backTestRangeEndStamp);
	}
	QCPFinancialDataContainer candleData;
	QSharedPointer<DateTimeTickerText> textTicker(new DateTimeTickerText);     // 文字轴
	textTicker->setTickCount(5);
	int pIndex = 0;
	for (std::deque<MData::KLineItem>::const_iterator it = pDataGather.GetKItems().begin(); it != pDataGather.GetKItems().end(); ++it, ++pIndex)
	{
		QCPFinancialData cpData(pIndex, it->Open, it->High, it->Low, it->Close);
		candleData.add(cpData);
		std::string tmStr = Tools::DateTimeStamp2Str(it->UpdateTime);
		textTicker->addTick(pIndex, QString::fromLocal8Bit(tmStr.c_str()));
	}
	m_candlesticks->data()->set(candleData);
	ui.centralWidget->xAxis->setTicker(textTicker);


	//QCPAxisRect *volumeAxisRect = new QCPAxisRect(ui.centralWidget);
	//ui.centralWidget->plotLayout()->addElement(1, 0, volumeAxisRect);
	//volumeAxisRect->setMaximumSize(QSize(QWIDGETSIZE_MAX, 100));
	//volumeAxisRect->axis(QCPAxis::atBottom)->setLayer("axes");
	//volumeAxisRect->axis(QCPAxis::atBottom)->grid()->setLayer("grid");
	//// bring bottom and main axis rect closer together:
	////customPlot->plotLayout()->setRowSpacing(0);
	//volumeAxisRect->setAutoMargins(QCP::msLeft | QCP::msRight | QCP::msBottom);
	//volumeAxisRect->setMargins(QMargins(0, 0, 0, 0));
	//volumeAxisRect->axis(QCPAxis::atBottom)->setTicker(textTicker);
	//connect(ui.centralWidget->xAxis, SIGNAL(rangeChanged(QCPRange)), volumeAxisRect->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange)));
	//connect(volumeAxisRect->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), ui.centralWidget->xAxis, SLOT(setRange(QCPRange)));

	MetricesPainter metricePainter(this, ui.centralWidget, pDataGather.GetKItems());
	metricePainter.DrawMetrices(pDataGather.GetMetrices());
	ui.centralWidget->rescaleAxes();
	ui.centralWidget->replot();
}

void MainView::onStrategyOption()
{
	QStringList symbolList;
	for (int i = 0; i <ui.list_symbols->count(); ++i)
	{
		symbolList << ui.list_symbols->item(i)->text();
	}
	StrategyOptionUI strategyDlg(symbolList, this);
	strategyDlg.exec();
}

void MainView::symbolListRightMenu(const QPoint &pos)
{
	QListWidgetItem* curItem = ui.list_symbols->itemAt(pos);
	if (curItem == nullptr)
		return;
	//QMenu *popMenu = new QMenu(this);
	//QString backTeskName = QString::fromWCharArray(L"回测%1").arg(curItem->text());
	//QAction *actBackTest = new QAction(backTeskName, this);
	//popMenu->addAction(actBackTest);
	//QObject::connect(actBackTest, &QAction::triggered, [this, curItem](bool checked) {
	//	// 将其他的全部不选
	//	onCheckStateChanged(Qt::Unchecked);
	//	ui.check_selectAll->setCheckState(Qt::PartiallyChecked);
	//	curItem->setCheckState(Qt::Checked);

	//	time_t backTestRangeBeginStamp, backTestRangeEndStamp;
	//	getCurBackTestTime(backTestRangeBeginStamp, backTestRangeEndStamp);
	//	std::string stdSymbolName = curItem->text().toLocal8Bit().data();
	//	std::string workspace = "E:/Work/CTPDocument/TqPyProject/WorkSpaceTest";
	//	BackTestOperator operTest(workspace,Tools::GetCurrentTimeStamp());
	//	operTest.BackTest(stdSymbolName, backTestRangeBeginStamp, backTestRangeEndStamp);
	//	// 之后将趋势绘制出来
	//	drawQuanitativeAndBackTest(stdSymbolName, backTestRangeBeginStamp, backTestRangeEndStamp);
	//	update();
	//});
	//popMenu->exec(QCursor::pos());
	//popMenu->deleteLater();
	//actBackTest->deleteLater();
}

void MainView::showKInfo(const QPoint &kPt)
{
	//MData::KLineItem  kItem;
	//if (!ui.centralWidget->GetQuantitativeCanvas().GetKItem(kPt, kItem))
	//{
	//	return;
	//}
	//KItemUI::Instance(this)->SetValue(kItem);
	//KItemUI::Instance(this)->show();

}

void MainView::onSetMDOpt()
{
	MDLoginSetting settingDlg(this);
	settingDlg.exec();
}

void MainView::onSetTradeOpt()
{
	TradeLoginSetting settingDlg(this);
	settingDlg.exec();
}

void MainView::onSetHolidayOpt()
{
	HolidayOptionUI holidayDlg(this);
	holidayDlg.exec();
}

void MainView::initSymbolListInfo()
{
	QDateTime lastBacktime = getLastBackTime();
	ui.date_test->setDateTime(lastBacktime);
	int pHour = lastBacktime.time().hour();
	if (pHour == 10)
	{
		ui.radio_moning->setChecked(true);
	}
	else if (pHour == 14)
	{
		ui.radio_afternoon->setChecked(true);
	}
	else
	{
		ui.radio_night->setChecked(true);
	}

	ui.dateTime_breakOn->setDateTime(QDateTime::currentDateTime());
}

void MainView::getCurBackTestTime(time_t &outBackTestRangeBeginStamp, time_t &outBackTestRangeEndStamp)
{
	QDateTime lastBacktime = getLastBackTime();
	// 获取回测时间
	tm backTestEndTm = Tools::GetDateTimeFrmStamp(lastBacktime.toTime_t());
	tm backTestRangeBegin, backTestRangeEnd;
	CTPTm::GetSegmentMarketRange(backTestEndTm, backTestRangeBegin, backTestRangeEnd);
	time_t backTestRangeBeginStamp = Tools::GetTimeStamp(backTestRangeBegin);
	backTestRangeBeginStamp -= 300;
	time_t backTestRangeEndStamp = Tools::GetTimeStamp(backTestRangeEnd);
	outBackTestRangeBeginStamp = backTestRangeBeginStamp;
	outBackTestRangeEndStamp = backTestRangeEndStamp;
}

void MainView::drawQuanitativeAndBackTest(const std::string &pSymbol, time_t backBegin, time_t backEnd)
{
	//tm quantitativeEnd = Tools::GetDateTimeFrmStamp(backBegin);
	//tm quantitativeBegin = CTPTm::GetWorkDayTimeBeforeDaysLen(quantitativeEnd, QuantityDays);
	//time_t quantitativeBeginStamp = Tools::GetTimeStamp(quantitativeBegin);
	//MDIO::KItem kItemReader;
	//std::deque<MData::KLineItem> allKItems;
	//kItemReader.ReadKItemsInTimes(pSymbol, quantitativeBeginStamp, backEnd, allKItems);

	//ui.centralWidget->ClearAllPainter();
	//QuantitativeCanvasGeometry &canvas = ui.centralWidget->GetQuantitativeCanvas();
	//canvas.InitCanvas(allKItems);
	//// 绘制K线
	//std::shared_ptr<KItemPainter> kPainter = std::make_shared<KItemPainter>(canvas);
	//ui.centralWidget->AppendQuantitativePainter(kPainter);
	//// 绘制量化周期
	//std::shared_ptr<CirclePainter> cirPaiter = std::make_shared<CirclePainter>(canvas);
	//std::string circlesDir = Tools::GetWorkSpace() + "/BreakPointCircles/";
	//std::string jsonPath = circlesDir + pSymbol + ".json";
	//std::shared_ptr<WaveFormData::WaveBreakPoint> _circle = WaveFormJson::ReadCircleFromJson(jsonPath);
	//cirPaiter->InitCircle(_circle);
	//ui.centralWidget->AppendQuantitativePainter(cirPaiter);
	//// 均线绘制
	//std::shared_ptr<MAPainter> maPainter = std::make_shared<MAPainter>(canvas);
	//maPainter->InitMAData(pSymbol);
	//ui.centralWidget->AppendQuantitativePainter(maPainter);
}

QDateTime MainView::getLastBackTime()
{
	QSettings settings(SynthesisSettingFile, QSettings::IniFormat);
	QDateTime pTime = settings.value(TheLastBackTestTime_Opt, QDateTime::currentDateTime()).toDateTime();
	return pTime;
}

void MainView::saveBackTime(const QDateTime &pTime)
{
	QSettings settings(SynthesisSettingFile, QSettings::IniFormat);
	settings.setValue(TheLastBackTestTime_Opt, pTime);
}

QDateTime MainView::getMarketTimeMiddle()
{
	QDateTime pDt = ui.date_test->dateTime();
	if (ui.radio_moning->isChecked())
	{
		pDt.setTime(QTime::fromString("10:00:00", "hh:mm:ss"));
	}
	else if (ui.radio_afternoon->isChecked())
	{
		pDt.setTime(QTime::fromString("14:00:00", "hh:mm:ss"));
	}
	else
	{
		pDt.setTime(QTime::fromString("22:00:00", "hh:mm:ss"));
	}
	return pDt;
}

void MainView::initCandles()
{
	m_candlesticks = new QCPFinancial(ui.centralWidget->xAxis, ui.centralWidget->yAxis);
	m_candlesticks->setName("Candlestick");
	m_candlesticks->setChartStyle(QCPFinancial::csCandlestick);
	//candlesticks->setWidth(binSize*0.9);
	m_candlesticks->setTwoColored(true);
	m_candlesticks->setBrushPositive(QColor(128, 30, 30));
	m_candlesticks->setBrushNegative(QColor(0, 240, 240));
	m_candlesticks->setPenPositive(QPen(QColor(128, 30, 30)));
	m_candlesticks->setPenNegative(QPen(QColor(0, 240, 240)));
	m_candlesticks->setSelectable(QCP::stSingleData);

	ui.centralWidget->yAxis->setTickLabels(false);
	ui.centralWidget->yAxis->setTicks(false);
	ui.centralWidget->xAxis->setBasePen(Qt::NoPen);
	ui.centralWidget->xAxis->setTickLabels(true);
	ui.centralWidget->xAxis->setTicks(true); // only want vertical grid in main axis rect, so hide xAxis backbone, ticks, and labels
	ui.centralWidget->xAxis->setSubTicks(false);
	ui.centralWidget->xAxis->setTickLength(0, 4);
	ui.centralWidget->xAxis->setRange(0, 8);

	ui.centralWidget->rescaleAxes();

	// 允许用户用鼠标拖动轴范围，用鼠标滚轮缩放，点击选择图形:
	ui.centralWidget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
	ui.centralWidget->axisRect()->setRangeZoomFactor(1.5, 1.005);
	//ui.centralWidget->xAxis->scaleRange(2.0, ui.centralWidget->xAxis->range().center());
	//ui.centralWidget->yAxis->scaleRange(1.005, ui.centralWidget->yAxis->range().center());

	ui.centralWidget->replot();
}
